home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / mailbox2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-13  |  51.1 KB  |  2,189 lines

  1. /* NOTE: because of size, the previous 'mailbox.c' has been
  2.  * split in 3 parts:
  3.  * mboxcmd.c, containing the 'mbox' subcommands, and
  4.  * mailbox.c, containing some user mailbox commands, and
  5.  * mailbox2.c, containing the remaining user commands.
  6.  * 921125 - WG7J
  7.  */
  8. /* There are only two functions in this mailbox code that depend on the
  9.  * underlying protocol, namely mbx_getname() and dochat(). All the other
  10.  * functions can hopefully be used without modification on other stream
  11.  * oriented protocols than AX.25 or NET/ROM.
  12.  *
  13.  * SM0RGV 890506, most work done previously by W9NK
  14.  *
  15.  *** Changed 900114 by KA9Q to use newline mapping features in stream socket
  16.  *    interface code; everything here uses C eol convention (\n)
  17.  *
  18.  *    Numerous new commands and other changes by SM0RGV, 900120
  19.  *
  20.  * Gateway function now support outgoing connects with the user's call
  21.  * with inverted ssid. Users can connect to system alias as well...
  22.  * See also several mods in socket.c,ax25.c and others
  23.  * 11/15/91, WG7J/PA3DIS
  24.  *
  25.  * Userlogging, RM,VM and KM commands, and R:-line interpretation
  26.  * added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
  27.  *
  28.  * Inactivity timeout-disconnect added 920325 and later - WG7J
  29.  *
  30.  * Removed mbox overhead from calling Convers directly from ax25 - KO4KS
  31.  * Several other additions - KO4KS
  32.  */
  33. #include <stdio.h>
  34. #include <time.h>
  35. #include <io.h>
  36. #include <ctype.h>
  37. #include <alloc.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #ifdef  UNIX
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #endif
  44. #include <dir.h>
  45. #include <dos.h>
  46. #include "global.h"
  47. #include "config.h"
  48. #include "timer.h"
  49. #include "proc.h"
  50. #include "socket.h"
  51. #include "usock.h"
  52. #include "session.h"
  53. #include "smtp.h"
  54. #include "dirutil.h"
  55. #include "telnet.h"
  56. #include "ftp.h"
  57. #include "ftpserv.h"
  58. #include "commands.h"
  59. #include "netuser.h"
  60. #include "files.h"
  61. #include "bm.h"
  62. #include "pktdrvr.h"
  63. #include "ax25.h"
  64. #include "mailbox.h"
  65. #include "ax25mail.h"
  66. #include "nr4mail.h"
  67. #include "cmdparse.h"
  68. #include "mailfor.h"
  69. #include "help.h"
  70.  
  71. extern int MAttended;
  72. extern char *MAttendedAt;
  73. extern char Mbpasswd[];
  74. extern int BbsUsers;
  75. extern char DFAR Only[];
  76. extern char DFAR CurUsers[];
  77. extern char DFAR Howtoend[];
  78. extern char DFAR MsgAborted[];
  79. extern char *skipwhite __ARGS((char *));
  80. extern char DFAR *findhome __ARGS((char *));
  81. extern FILE *fopennew __ARGS((char *fname, char *mode));
  82. extern int searchfile __ARGS((char *searchfor,char *fname,char * buf,int entrysize,int *passes,int searchlen));
  83. extern int doipheard __ARGS((int argc,char *argv[],void *p));
  84. extern char *Mbhaddress;
  85.  
  86.  
  87. #ifdef MAILBOX
  88. static int uuencode __ARGS((FILE *infile,int s,char *infilename));
  89. int dodownload __ARGS((int argc,char *argv[],void *p));
  90. int dombfdesc __ARGS((int argc,char *argv[],void *p));
  91. int dombupload __ARGS((int argc,char *argv[],void *p));
  92. int dobump __ARGS((int argc,char *argv[],void *p));
  93. int msgidcheck __ARGS((char *string));
  94. int dombwpages __ARGS((int argc,char *argv[],void *p));
  95. int dombnews __ARGS((int argc,char *argv[],void *p));
  96. int dombtutor __ARGS((int argc,char *argv[],void *p));
  97. int dombgroup __ARGS((int argc,char *argv[],void *p));
  98. int dombquote __ARGS((int argc,char *argv[],void *p));
  99. int dombtime __ARGS((int argc,char *argv[],void *p));
  100. void quickscan __ARGS((struct mbx *m, int olduser));
  101. int dombset __ARGS((int argc,char *argv[],void *p));
  102. int dombrmail __ARGS((int argc,char *argv[],void *p));
  103. int dombroute __ARGS((int argc,char *argv[],void *p));
  104. int dombexpand __ARGS((int argc,char *argv[],void *p));
  105. int dombexpert __ARGS((int argc,char *argv[],void *p));
  106. int dombslip __ARGS((int argc,char *argv[],void *p));
  107. int douser __ARGS((int argc,char *argv[],void *p));
  108. int doreply __ARGS((int argc,char *argv[],void *p));
  109. int dombget __ARGS((int argc,char *argv[],void *p));
  110. int dombmovemail __ARGS((int argc,char *argv[],void *p));
  111. int dombhelp __ARGS((int argc,char *argv[],void *p));
  112. int dombconvers __ARGS((int argc,char *argv[],void *p));
  113. int dombtelnet __ARGS((int argc,char *argv[],void *p));
  114. int dombfinger __ARGS((int argc,char *argv[],void *p));
  115. int dosysop __ARGS((int argc,char *argv[],void *p));
  116. int dostars __ARGS((int argc,char *argv[],void *p));
  117. int dochat __ARGS((int argc,char *argv[],void *p));
  118. int dombjheard __ARGS((int argc,char *argv[],void *p));
  119. int dombiproute __ARGS((int argc,char *argv[],void *p));
  120. #ifdef LZW
  121. void togglelzw __ARGS((int soc, int mode));
  122. #endif
  123. #ifdef WPAGES
  124. void wpageAdd __ARGS((char *entry, int bbs, int updateit));
  125. char *wpageCheck __ARGS((char *string,int bbs, int updateit));
  126. #endif
  127. char *wpage_exp __ARGS((char *to,int hier,int exphome));
  128. int dozap __ARGS((int argc,char *argv[],void *p));
  129. int dowhat __ARGS((int argc,char *argv[],void *p));
  130. extern int gw_connect __ARGS((struct mbx *m,int s,struct sockaddr *fsocket,int len));
  131. extern int dosend __ARGS((int argc,char *argv[],void *p));
  132. extern char *permtest __ARGS((char *path,long privs,char *name,int mode,char *root,int dir));
  133. extern char *cmd_line __ARGS((int argc,char *argv[],char stype));
  134. extern char *nntp_name_expansion __ARGS((char *name));
  135.  
  136.  
  137. static char DFAR Alsomenu[] = "\nFor further help, type 'help cmdname', where 'cmdname' is one of the above.\n\
  138. For a brief listing of all commands, type '?'\n\n\
  139. Others: AF, AL, AN, AS, DU, KM, KS, KU, L$, L>, L<, LA, LB, LL, LM, LS, LT,\n\
  140.         ML, MS, RH, RM, SB, SC, SF, SP, SR, ST, VM, XA, XC, XM, XN, XS\n";
  141. static char DFAR Sysopmenu[] =  "Sysops: IF, MA, MC, MF, MH, MK, MM, MP, MR, MT, MW, MX, WA, WR, @\n";
  142. static char DFAR index_dat[] = "index.dat";
  143.  
  144. short SecureTelnet = 1;
  145.  
  146.  
  147. int
  148. dowhat(argc,argv,p)
  149. int argc;
  150. char *argv[];
  151. void *p;
  152. {
  153. struct mbx *m;
  154. FILE *fp, *in = NULLFILE;
  155. char *file;
  156. char *args[3];
  157. char *cp, *nm, *ptr;
  158. char buf[50], buf2[80];
  159. int yep;
  160. unsigned attr;
  161.             
  162.     m = (struct mbx *)p;
  163. #ifdef WPAGES
  164.     if (m->stype == 'P')
  165.         return (dombwpages (argc, argv, p));
  166. #endif
  167.     if(((m->stype == 'R') || (m->stype == 'A')) && !(m->privs & SYSOP_CMD)){
  168.         tputs ("Sorry, command is only available to the SYSOP!\n");
  169.         return 0;
  170.     }
  171.     if (m->stype == 'R')    {
  172.         if(argc < 3)
  173.             tputs("Syntax: WR user \"message\"\n");
  174.         else    {
  175.             dowrite (0, argv, 0);
  176.         }
  177.         return 0;
  178.     }
  179.     if (m->stype == 'A')    {
  180.         if(argc < 2)
  181.             tputs("Syntax: WA \"message\"\n");
  182.         else    {
  183.             dowriteall (0, argv, 0);
  184.         }
  185.         return 0;
  186.     }
  187.     if ((file = permtest (m->path, m->privs, (argc > 1) ? argv[1] : ".", RETR_CMD, NULLCHAR, (argc < 2))) != NULLCHAR)        {
  188.         m->state = MBX_WHAT;
  189.  
  190.         /* check for index.dat file in that directory */
  191.         cp = strdup (file);
  192.         _dos_getfileattr (cp, &attr);
  193.         if(!(attr & FA_DIREC))    {
  194.             ptr = strrchr (cp, '/');
  195.             *ptr = 0;
  196.         }
  197.         nm = pathname (cp,index_dat);
  198.         free (cp);
  199.         in = fopen (nm, READ_TEXT);
  200.         free (nm);
  201.         if (in != NULLFILE)    {
  202.             tputc ('\n');
  203.             while (fgets (buf2, 80, in) != NULLCHAR) {
  204.                 if (*buf2 == ' ' || *buf2 == '\t' || *buf2 == '\n')
  205.                     tputs (buf2);
  206.                 else
  207.                     break;
  208.             }
  209.         }
  210.  
  211.         if((fp = dir(file, (in == NULLFILE) ? 1 : 2)) == NULLFILE)
  212.             tprintf("Can't read directory: \"%s\": %s\n",file,sys_errlist[errno]);
  213.         else    {
  214. #ifdef MBXTDISC
  215.                 stop_timer(&m->tdisc);
  216. #endif
  217.             if (in == NULLFILE)
  218.                 sendfile(fp,m->user,ASCII_TYPE,0);
  219.             else    {
  220.                 while (fgets(buf,50,fp)!= NULLCHAR) {
  221.                     yep = 0;
  222.                     if (*buf == ' ')
  223.                         continue;
  224.                     rewind (in);
  225.                     while (fgets (buf2, 80, in) != NULLCHAR)    {
  226.                         if (!strnicmp (buf, buf2, 12))    {
  227.                             yep = 1;
  228.                             rip (buf2);
  229.                             break;
  230.                         }
  231.                     }
  232.                     if (yep)
  233.                         rip (buf);
  234.                     tputs (buf);
  235.                     if (yep)    {
  236.                         ptr = &buf2[13];
  237.                         ptr = skipwhite (ptr);
  238.                         tprintf ("%-37.37s\n", ptr);
  239.                         while (fgets (buf2, 80, in) != NULLCHAR)    {
  240.                             if (*buf2 != ' ' && *buf2 != '\t')
  241.                                 break;
  242.                             rip (buf2);
  243.                             ptr = skipwhite (buf2);
  244.                             tprintf ("%39s| %-37.37s\n", "", ptr);
  245.                         }
  246.                     }
  247.                 }
  248.                 fclose (in);
  249.             }
  250.             fclose(fp);
  251.         }
  252.         free(file);
  253.     } else    {
  254.         tputs(Noperm);
  255.             mail_error("%s: directory denied: %s\n",m->name,cmd_line(argc,argv,m->stype));
  256.     }
  257.     return 0;
  258. }
  259.  
  260. int
  261. dozap(argc,argv,p)
  262. int argc;
  263. char *argv[];
  264. void *p;
  265. {
  266. struct mbx *m;
  267. char *file;
  268.  
  269.     m = (struct mbx *)p;
  270.     if ((file = permtest (m->path, m->privs, argv[1], DELE_CMD, NULLCHAR, 0)) != NULLCHAR)    {
  271.         if(unlink(file))
  272.             tprintf("Zap failed: %s\n",sys_errlist[errno]);
  273.         else
  274.             log(m->user,"MBOX Zap: %s",file);
  275.         free(file);
  276.     } else    {
  277.         tputs(Noperm);
  278.             mail_error("%s: zap denied: %s\n",m->name,cmd_line(argc,argv,m->stype));
  279.     }
  280.     return 0;
  281. }
  282.  
  283.  
  284. extern void dumproute __ARGS((struct route *rp,char *p));
  285. extern char RouteHeader[];
  286.  
  287. /* Show non-private routes only */
  288. int
  289. dombiproute(argc,argv,p)
  290. int argc;
  291. char *argv[];
  292. void *p;
  293. {
  294.     register int i,bits;
  295.     register struct route *rp;
  296.     char buf[85];
  297.  
  298.     tputs(RouteHeader);
  299.     for(bits=31;bits>=0;bits--){
  300.         for(i=0;i<HASHMOD;i++){
  301.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  302.                 if(!(rp->flags & RTPRIVATE)) {
  303.                     dumproute(rp,buf);
  304.                     if(tprintf("%s\n",&buf[4]) == EOF)
  305.                         return 0;
  306.                 }
  307.             }
  308.         }
  309.     }
  310.     if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)) {
  311.         dumproute(&R_default,buf);
  312.         if(tprintf("%s\n",buf) == EOF)
  313.             return 0;
  314.     }
  315.     return 0;
  316. }
  317.  
  318.  
  319. #ifdef AX25
  320. int
  321. dombjheard(argc,argv,p)
  322. int argc;
  323. char *argv[];
  324. void *p;
  325. {
  326.     struct iface *ifp;
  327.     struct mbx *m = (struct mbx *)p;
  328.  
  329.     if(argc > 1){
  330.         if( ((ifp = if_lookup(argv[1])) == NULLIF) || (ifp->type != CL_AX25) ||
  331.            ((ifp->flags & HIDE_PORT) && !(m->privs & MBX_SYSOP)) ) {
  332.             tprintf(Badinterface,argv[1]);
  333.             return 0;
  334.         }
  335.         axheard(ifp);
  336.         return 0;
  337.     }
  338.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  339.         if((ifp->flags & LOG_AXHEARD)  && ( !(ifp->flags & HIDE_PORT) || m->privs&MBX_SYSOP) )
  340.             if(axheard(ifp) == EOF)
  341.                 break;
  342.     }
  343.     return 0;
  344. }
  345. #endif
  346.  
  347.  
  348. char SysopBusy[] = "The system is unattended. Try again later.\n";
  349.  
  350. int
  351. dochat(argc,argv,p)
  352. int argc;
  353. char *argv[];
  354. void *p;
  355. {
  356. char buf[8], *newargv[3], doat[50];
  357. struct mbx *m;
  358.  
  359.     m = (struct mbx *)p;
  360.  
  361.     if(MAttended){
  362.         m->state = MBX_CHAT;
  363.         newargv[0] = "C";
  364.         newargv[1] = Hostname;
  365.         if(MAttendedAt != NULLCHAR)    {
  366.             strcpy (doat, MAttendedAt);
  367.             newargv[1] = doat;
  368.             rip (newargv[1]);
  369.         }
  370.         sprintf(buf,"%d",IPPORT_TTYLINK);
  371.         newargv[2] = buf;
  372.         SecureTelnet = 0;
  373.         return dombtelnet(3,newargv,p);
  374.     }
  375.     else
  376.             tputs(SysopBusy);
  377.  
  378.     /* It returns only after a disconnect or refusal */
  379.     return 0;
  380. }
  381.  
  382. /*Password protection added - 920118, WG7J */
  383. int
  384. dosysop(argc,argv,p)
  385. int argc;
  386. char *argv[];
  387. void *p;
  388. {
  389. struct mbx *m;
  390. int c;
  391. int len,pwdc[5],i,valid=0;
  392. char *cp;
  393. extern struct cmds DFAR Cmds[];
  394.  
  395.     m = (struct mbx *) p;
  396.     log(m->user,"MBOX: %s attempting SYSOP",m->name);
  397.  
  398.     /*If you want anyone with the password to go sysop-mode
  399.      *comment out the next 4 line ! -WG7J
  400.      */
  401.     if(!(m->privs & SYSOP_CMD))    {
  402.         tputs(Noperm);
  403.         mail_error("%s: SYSOP denied!\n",m->name);
  404.         return 0;
  405.     }
  406.  
  407.     /*only if set,
  408.      *check for the password before letting users proceed
  409.      */
  410.     m->state = MBX_SYSOPTRY;
  411.     if((len = strlen(Mbpasswd)) != 0) {
  412.             for (i=0;i<5;i++)
  413.             tprintf("%d ",(pwdc[i]=random(len)) + 1); /*print the random chars*/
  414.         tputc('\n');
  415.         while(1)     {
  416.             c = mbxrecvline(m);
  417.             if(c == EOF || c == -2)
  418.                 return 0;
  419.             if(*m->line == '\0')
  420.                 break;
  421.             if (*m->line == '?')    {
  422.                 tprintf ("Validation %somplete!\n", valid ? "C" : "Inc");
  423.                 continue;
  424.             }
  425.             cp = m->line;
  426.             for(i=0;i<5;i++)
  427.                 if(tolower(*cp++) != tolower(Mbpasswd[pwdc[i]]))
  428.                     break;
  429.             if (i == 5)
  430.                 valid = 1;
  431.         }
  432.         if(!valid)
  433.             return 0;
  434.     }
  435.  
  436.     log(m->user,"MBOX: %s is now SYSOP",m->name);
  437.     m->state = MBX_SYSOP;
  438.     tputs("\n\aType 'exit' to return\n\nBe VERY careful!!\n");
  439.  
  440.     for(;;)        {
  441.         netPrompt ();
  442.         usflush(Curproc->output);
  443.         if(mbxrecvline(m) < 0)
  444.             break;
  445.         log(m->user,"MBOX sysop: %s",m->line);
  446. #ifdef MBXTDISC
  447.         stop_timer(&m->tdisc);
  448. #endif
  449.         valid = cmdparse(Cmds,m->line,NULL);
  450. #ifdef MBXTDISC
  451.         start_timer(&m->tdisc);
  452. #endif
  453.         if (valid == -2)
  454.             break;
  455.     }
  456.     return 0;
  457. }
  458.  
  459. /* Handle the "*** Done" command when reverse forwarding ends or the
  460.  * "*** LINKED to" command.
  461.  */
  462. int
  463. dostars(argc,argv,p)
  464. int argc;
  465. char *argv[];
  466. void *p;
  467. {
  468. struct mbx *m;
  469. int anony = 1;
  470. int founddigit = 0;
  471. int oldprivs;
  472. char *cp;
  473.  
  474.     m = (struct mbx *)p;
  475.  
  476.     /* The "*** LINKED to" command is only allowed to stations with
  477.      * SYSOP privileges to prevent others from obtaining the same.
  478.      */
  479. #ifdef notdef
  480.     if((m->privs & SYSOP_CMD) && argc == 4 && !strcmp(argv[1],"linked")) {
  481. #endif
  482.     /* Allow 'linked to' from anyone, but reset SYSOP priviledges
  483.      * when the sysop-password is not set !
  484.      * Also try to set the new call !
  485.      * Inspired by Kurt, wb5bbw
  486.      * Check for the strange TEXNET linked message !
  487.      * 920220 - WG7J
  488.      */
  489.     if((argc >= 4) && !strcmp(argv[1],"linked") && !strcmp(argv[2],"to") ) {
  490. #ifdef GWTRACE
  491.         log(m->user,"MBOX LINKED: %s changed to %s",m->name,argv[3]);
  492. #endif
  493.         strcpy(m->name,argv[3]);
  494.         oldprivs = m->privs; /*Save this !*/
  495.         /* Try to find the privileges of this user from the userfile */
  496.         if((m->privs = userlogin(m->name,NULLCHAR,&m->path,MBXLINE,
  497.                      &anony)) == -1)
  498.              if((m->privs = userlogin("bbs",NULLCHAR,&m->path,
  499.                       MBXLINE,&anony)) == -1)
  500.               if((m->privs = userlogin("anonymous",NULLCHAR,
  501.                        &m->path,MBXLINE,&anony)) == -1){
  502.                         m->privs = 0;
  503.                         free(m->path);
  504.                         m->path = NULLCHAR;
  505.               }
  506.         if(m->privs & EXCLUDED_CMD)
  507.             return domboxbye(0,NULLCHARP,p);
  508. #ifdef AX25
  509.         /* Set the call */
  510.         for(cp=m->name;*cp != '\0';cp++)
  511.             if(isdigit((int)*cp))
  512.                 break;
  513.         if(*cp != '\0')
  514.             founddigit = 1;
  515.         if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
  516.             m->privs &= ~AX25_CMD;
  517.             m->privs &= ~NETROM_CMD;
  518.         }
  519. #else
  520.         m->privs &= ~AX25_CMD;
  521.         m->privs &= ~NETROM_CMD;
  522. #endif
  523.         /*Kill ssid in name, if any*/
  524.         if((cp=strchr(m->name,'-')) != NULLCHAR)
  525.             *cp = '\0';
  526.         /*Check if sysop password is set,
  527.          *if not, disallow sysop privs no matter what !
  528.          */
  529.         if(*Mbpasswd == '\0')
  530.             m->privs &= ~SYSOP_CMD;
  531.         /*Check to see if any of NO_READ,NO_SEND or NO_3PARTY were set,
  532.          *if so, dis-allow those no matter what
  533.          *(so that users cannot get priviledges by issuing a ***linked)
  534.          * 920220 - WG7J
  535.          */
  536.         if(oldprivs & NO_SENDCMD)
  537.             m->privs |= NO_SENDCMD;
  538.         if(oldprivs & NO_READCMD)
  539.             m->privs |= NO_READCMD;
  540.         if(oldprivs & NO_3PARTY)
  541.             m->privs |= NO_3PARTY;
  542.  
  543.         tprintf("Oh, hello %s.\n",m->name);
  544.         changearea(m,m->name, (int) 1);
  545.         return 0;
  546.     }
  547.     if(argc > 1 && (m->sid & MBX_SID))    /* "*** Done" or similar */
  548.             return -2;
  549.     return -1;
  550. }
  551.  
  552.  
  553. int
  554. dombtelnet(argc,argv,p)
  555. int argc;
  556. char *argv[];
  557. void *p;
  558. {
  559. struct mbx *m;
  560. int s, len, i;
  561. char dsocket[MAXSOCKSIZE];
  562. struct sockaddr_in fsocket;
  563.  
  564.     m = (struct mbx *) p;
  565.     fsocket.sin_family = AF_INET;
  566.     if(argc < 3)
  567.         fsocket.sin_port = IPPORT_TELNET;
  568.     else
  569.         fsocket.sin_port = atoip(argv[2]);
  570.  
  571.     if((fsocket.sin_addr.s_addr = resolve(argv[1])) == 0){
  572.         tprintf(Badhost,argv[1]);
  573.         /* Free m->starmsg if set ! - WG7J */
  574.         if(m->startmsg != NULLCHAR) {
  575.             free(m->startmsg);
  576.             m->startmsg = NULLCHAR;
  577.         }
  578.         return 0;
  579.     }
  580.     /* Only local telnets are are allowed to the unprivileged user */
  581.     /* The above is a security hole ! DO NOT allow this anymore ! - WG7J */
  582.  
  583.     /* If the first letter of the command is 'C', then it was
  584.      * the CALL,QUERY,OPERATOR or CONFERENCE command !
  585.      * Allow these, no matter what.
  586.      * This way, you can give access to the Internet callserver,
  587.      * but disable all other telnets - WG7J
  588.      */
  589.     if(SecureTelnet && *argv[0] != 'C') {
  590.         if(!(m->privs & TELNET_CMD) /* && !ismyaddr(fsocket.sin_addr.s_addr)*/ ){
  591.             tputs(Noperm);
  592.             mail_error("%s: Telnet denied: %s\n",m->name,cmd_line(argc,argv,m->stype));
  593.             /* Free m->starmsg if set ! - WG7J */
  594.             /* Shouldn't happen here, but just in case */
  595.             if(m->startmsg != NULLCHAR) {
  596.                 free(m->startmsg);
  597.                 m->startmsg = NULLCHAR;
  598.             }
  599.             return 0;
  600.         }
  601.     }
  602.     SecureTelnet = 1;
  603.     if((s = socket(AF_INET,SOCK_STREAM,0)) == -1){
  604.         tputs(Nosock);
  605.         /* Free m->starmsg if set ! - WG7J */
  606.         if(m->startmsg != NULLCHAR) {
  607.             free(m->startmsg);
  608.             m->startmsg = NULLCHAR;
  609.         }
  610.         return 0;
  611.     }
  612. #ifdef GWTRACE
  613.     log(m->user,"MBOX TELNET: %s to %s:%d",m->name,argv[1],fsocket.sin_port);
  614. #endif
  615.     if(fsocket.sin_port == IPPORT_TTYLINK) {
  616.         m->startmsg = mallocw(80);
  617.         len = MAXSOCKSIZE;
  618.         i = getpeername(m->user,dsocket,&len);
  619.         sprintf(m->startmsg,"*** Incoming call from %s@%s ***\n",
  620.             m->name,i != -1 ? psocket(dsocket): Hostname);
  621.     }
  622.     m->state = MBX_GATEWAY;
  623.     return gw_connect(m,s,(struct sockaddr *)&fsocket,SOCKSIZE);
  624. }
  625.  
  626. int
  627. dombfinger(argc,argv,p)
  628. int argc;
  629. char *argv[];
  630. void *p;
  631. {
  632. struct mbx *m;
  633. char *host, *user = NULLCHAR, buf[8], *newargv[3];
  634.  
  635.     if(argc > 2){
  636.         tputs("Usage: F user@host  or  F @host  or  F user.\n");
  637.         return -1;
  638.     }
  639.     host = Hostname;
  640.     if(argc == 2){
  641.         if((host = strchr(argv[1], '@')) != NULLCHAR){
  642.             *host = '\0';
  643.             host++;
  644.         } else
  645.             host = Hostname;
  646.         user = argv[1];
  647.     }
  648.     m = (struct mbx *) p;
  649.     m->startmsg = mallocw(80);
  650.     if(user != NULLCHAR)
  651.         sprintf(m->startmsg,"%s\n",user);
  652.     else
  653.         strcpy(m->startmsg,"\n");
  654.     newargv[0] = "t";
  655.     newargv[1] = host;
  656.     sprintf(buf,"%d",IPPORT_FINGER);
  657.     newargv[2] = buf;
  658.     SecureTelnet = 0;
  659.     return dombtelnet(3,newargv,p);
  660. }
  661.  
  662.  
  663. extern int Mbconverse;
  664.  
  665. #ifdef  CONVERS
  666. int
  667. dombconvers(argc,argv,p)
  668. int argc;
  669. char *argv[];
  670. void *p;
  671. {
  672. struct mbx *m;
  673. int channel = -1, x, y;
  674. struct session *sp;
  675.  
  676.     m = (struct mbx *) p;
  677.  
  678.         if(!Mbconverse) {
  679.             tputs("Conference server not enabled\n");
  680.             return 0;
  681.         }
  682.     if(argc != 1)
  683.         channel = atoi (argv[1]);
  684. #ifdef GWTRACE
  685.         log(m->user,"MBOX CONFERENCE: %s",m->name);
  686. #endif
  687.         m->state = MBX_CONVERS;
  688.     usflush(Curproc->output);
  689.     if (Current->type == 1)
  690.         tprintf ("%c%c", IAC, CLEARSCREEN);    /* sets Current->split */
  691.     sp = Current;
  692.     pwait (NULL);
  693.         mbox_converse(m->user, m->name, channel, m);
  694.     if (sp->split)    {
  695.         usflush(Curproc->output);
  696.         tprintf ("%c%c", IAC, CLEARSPLIT);    /* clears Current->split */
  697.         usflush(Curproc->output);
  698.             sp->split = 0;
  699.     }
  700.     return 0;
  701. }
  702. #endif
  703.  
  704. #ifdef TUTOR
  705. extern int Sinfo;
  706. #endif
  707.  
  708. int
  709. dombhelp(argc,argv,p)
  710. int argc;
  711. char *argv[];
  712. void *p;
  713. {
  714. char buf[255];
  715. int i;
  716. FILE *fp;
  717. struct mbx *m;
  718.  
  719.     m = (struct mbx *)p;
  720.  
  721.     if ((m->stype == 'F') && (m->privs & SYSOP_CMD))    {
  722.         forwardingSummary ();
  723.         return 0;
  724.     }
  725.     if (m->stype == 'H')
  726.         return (doipheard (argc, argv, p));
  727.         
  728.     buf[0] = '\0';
  729.     /* check for "?" and "help" here */
  730.     if(*argv[0] == '?' || *argv[0] == 'h') {
  731.         bbscolorcls (m);
  732.         bbscolorchange (m, "07");
  733.         dombxhelp (argc, argv, p);
  734.         if (*argv[0] == '?' && argc == 1)    {
  735.             bbscolorchange (m, "0B");
  736.             tputs(Alsomenu);
  737.             if (m->privs & SYSOP_CMD)
  738.                 tputs(Sysopmenu);
  739.             bbscolorchange (m, "09");
  740.             sprintf(buf,"%s/help.hlp",Helpdir);
  741.             goto also;
  742.         }
  743.         return 0;
  744.     }
  745. #ifdef TUTOR
  746.     if (Sinfo != -1)    {
  747.             log(m->user,"MBOX TUTORIAL: %s",m->name);
  748.                m->state = MBX_TUTOR;
  749.                tutorserv(m->name, m, 1, m->usecolor, 0);
  750.            } else    {
  751. #endif
  752.         tprintf(Nosversion,Version);
  753.         tprintf ((BbsUsers == 1) ? Only : CurUsers, BbsUsers);
  754.         sprintf(buf,"%s/sysinfo.hlp",Helpdir);
  755. also:        if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
  756.             sendfile(fp,Curproc->output,ASCII_TYPE,0);
  757.             fclose(fp);
  758.         } else {
  759.             if(argc > 1 && *argv[0] == 'h')
  760.             tputs("No help available.\n");
  761.         }
  762. #ifdef TUTOR
  763.     }
  764. #endif
  765.     return 0;
  766. }
  767.  
  768. extern char Badmsg[];
  769. extern char Nomail[];
  770.  
  771. /* Move messages from current area to another */
  772. int
  773. dombmovemail(argc,argv,p)
  774. int argc;
  775. char *argv[];
  776. void *p;
  777. {
  778. int num,i;
  779. int movebuf[NARG];
  780. char *to;
  781. struct mbx *m;
  782. char buf[MBXLINE];
  783. char *cp;
  784. FILE * Mfile;           /* file to move to */
  785. struct let *cmsg;
  786. long size;
  787. int thisone, wrcntr;
  788. #ifdef nope
  789. int nextisBID;
  790. long msgid;
  791. #endif
  792. struct let lt;
  793.  
  794.     m = (struct mbx *)p;
  795.  
  796.     if(argc == 1) {
  797.     char *which;
  798.     which = (m->stype == 'M') ? "move" : (m->stype == 'W') ? "write" : "copy";
  799.         tprintf("Syntax: M%s area - %s current message\n        M%s n1 [n2...] %s - %s message n1 (n2...)\n",
  800.         m->stype, which, m->stype, (m->stype == 'W') ? "filename" : "area", which);
  801.         return 0;
  802.     }
  803.     if(m->mfile == NULLFILE) {
  804.         tputs(Nomail);
  805.         return 0;
  806.     }
  807.     if(argc == 2) {
  808.         /* NO message #, use current message */
  809.         num = 1;
  810.         to = argv[1];
  811.         movebuf[0] = m->current;
  812.     } else {
  813.         /* Scan all message # to move */
  814.         num=0;
  815.         for(i=1;i<argc-1;i++) {
  816.             if( (movebuf[num]=atoi(argv[i])) != 0 )
  817.                 if(movebuf[num] <= m->nmsgs)
  818.                     num++;
  819.             else
  820.                 tprintf(Badmsg,argv[i]);
  821.         }
  822.         to = argv[argc-1];
  823.     }
  824. #ifdef notdef
  825.     /* translate '.' and '\' to '/' */
  826.     for(cp=to;*cp!='\0';cp++)
  827.         if((*cp == '.') || (*cp == '\'))
  828.             *cp = '/';
  829. #else
  830.     if (m->stype != 'W')
  831.         nntp_name_expansion (to);
  832. #endif
  833.  
  834.     /* Now try to lock the destination file, if not a write */
  835.     if(m->stype != 'W')
  836.         if(mlock(Mailspool,to) == -1) {
  837.             tprintf("Can't lock '%s', please try later\n",to);
  838.             return 0;
  839.             }
  840.     /* open the destination file for appending */
  841.     if (m->stype == 'W')    {
  842.         char *p;
  843.         p = permtest (m->path, m->privs, to, STOR_CMD, NULLCHAR, 0);
  844.         if (!p)
  845.             return 0;
  846.     strcpy (buf,p);
  847.     free (p);
  848.     } else 
  849.     sprintf(buf,"%s/%s.txt",Mailspool,to);
  850.     if((Mfile=fopen(buf,"a")) == NULLFILE) {
  851.         tprintf("Can't open '%s'\n",buf);
  852.         if (m->stype != 'W')
  853.             rmlock(Mailspool,to);
  854.         return 0;
  855.     }
  856. #ifdef nope
  857.     nextisBID = 0;
  858. #endif
  859.     /* Okay, let's do the work */
  860.     for(i=0;i<num;i++) {
  861.         thisone = movebuf[i];
  862.         cmsg = &m->mbox[thisone];
  863.         /* find start of this message */
  864.         fseek(m->mfile,cmsg->start,0);
  865.         size = cmsg->size;
  866.         fflush (Mfile);
  867.         lt.size = cmsg->size;
  868.         lt.bid = cmsg->bid;
  869.         lt.status = 0;
  870.         lt.start = filelength (fileno(Mfile));
  871.     wrcntr = 0;
  872.         
  873.         /* now read this message */
  874.         while(size > 0 && fgets(buf,MBXLINE,m->mfile)!= NULLCHAR) {
  875.         pwait (NULL);
  876.         if (m->stype != 'W' || wrcntr > 2)
  877.                 fputs(buf,Mfile);
  878.         wrcntr += 1;
  879. #ifdef nope
  880.         if (nextisBID && (cp=strstr(buf,"AA")) != NULLCHAR) {
  881.         /*what follows is the message-number*/
  882.         msgid = atol(cp+2);
  883.         nextisBID = 0;
  884.         }
  885.             if (!strncmp (Hdrs[RECEIVED], buf, strlen(Hdrs[RECEIVED])))
  886.                 nextisBID = 1;
  887. #endif                        
  888.             size -= strlen(buf);
  889.         }
  890. #ifdef USERLOG
  891.         updateCtl (to, <);
  892. #endif
  893.         /* delete this message, if moving */
  894.         if (m->stype == 'M')    {
  895.             cmsg->status |= BM_DELETE;
  896.         statusCtl (m->area, "ctl", cmsg, thisone, 0);
  897.         if (!issysarea (m->area))
  898.                    m->change |= CHG_DELETE;
  899.         }
  900.     tprintf("Message %d %s...\n",thisone, (m->stype == 'M') ? "moved" : (m->stype == 'W') ? "written" : "copied");
  901.     }
  902.     fclose(Mfile);
  903.     if (m->stype != 'W')
  904.         rmlock(Mailspool,to);
  905.     return 0;
  906. }
  907.  
  908.  
  909. static int
  910. expertstat (m)
  911. struct mbx *m;
  912. {
  913. char *p;
  914. int flag;
  915.  
  916.     switch(m->stype) {
  917.         case 'M':    tprintf("-more- after %d lines\n",m->morerows);
  918.                 return 0;
  919.         case 'A':    p = "Area added to prompt";
  920.                 flag = m->sid & MBX_AREA;
  921.                 break;
  922.         case 'N':    p = "Name added to prompt";
  923.                 flag = m->sid & MBX_NRID;
  924.                 break;
  925.         case 'S':    p = "New message scan at login";
  926.                 flag = m->sid & MBX_STATS;
  927.                 break;
  928.         case 'G':    p = "Use ANSI color graphics";
  929.                 flag = m->sid & MBX_GFX;
  930.                 break;
  931. #ifdef LZW
  932.         case 'C':    p = "Use Compressed streams";
  933.                 flag = m->sid & MBX_TNOS;
  934.                 break;
  935. #endif
  936.         case 'X':
  937.         case ' ':       p = "Expert user prompts";
  938.                 flag = m->sid & MBX_EXPERT;
  939.                 break;
  940.         default:        return 0;
  941.     }
  942.     tprintf ("%s: o%s\n", p, (flag) ? "n" : "ff");
  943.     return 0;
  944. }
  945.  
  946.  
  947. int
  948. dombgetall (m)
  949. struct mbx *m;
  950. {
  951. char *args[2];
  952.  
  953.     tprintf ("*** User profile settings: %s ***\n\n", m->name);
  954.     m->stype = 'M';        expertstat (m);
  955.     m->stype = 'A';        expertstat (m);
  956.     m->stype = 'N';        expertstat (m);
  957.     m->stype = 'S';        expertstat (m);
  958.     m->stype = 'G';        expertstat (m);
  959.     m->stype = 'C';        expertstat (m);
  960. #ifdef LZW
  961.     m->stype = 'X';        expertstat (m);
  962. #endif
  963.     args[1] = "F";        dombget(2, args, m);
  964.     args[1] = "Si";        dombget(2, args, m);
  965.     tprintf ("\nUse the SET command to change these options. For help, type HELP SET.\n");
  966.     return 0;
  967. }
  968.  
  969.  
  970. int
  971. dombget(argc,argv,p)
  972. int argc;
  973. char *argv[];
  974. void *p;
  975. {
  976. struct mbx *m;
  977. int cnt;
  978.  
  979.     if (argc == 1)
  980.         return (dombgetall(p));
  981.     m = (struct mbx *)p;
  982.     m->stype = toupper (*argv[1]);
  983.     if (m->stype != 'F' && strnicmp(argv[1], "Si", 2))
  984.         return (expertstat(m));
  985.     sprintf (m->line, "%s/%s%s", (m->stype == 'F') ? Fdir : Signature, m->name, (m->stype == 'S') ? ".sig" : "");
  986.     tprintf ("---------------- Current %s Information ----------------\n", (m->stype == 'F') ? "Finger" : "Signature");
  987.     cnt = DisplayFile(m->line, m->user);
  988.     tprintf ("---------------- %s %s Information ----------------\n", (cnt) ? "End of" : "No", (m->stype == 'F') ? "Finger" : "Signature");
  989.     return 0;
  990. }
  991.  
  992.  
  993. int
  994. doreply(argc,argv,p)
  995. int argc;
  996. char *argv[];
  997. void *p;
  998. {
  999. register struct mbx *m;
  1000.  
  1001.     m = (struct mbx *)p;
  1002.     m->stype = 'R';
  1003.     return (dosend (argc, argv, p));
  1004. }
  1005.  
  1006. int
  1007. douser(argc,argv,p)
  1008. int argc;
  1009. char *argv[];
  1010. void *p;
  1011. {
  1012. register struct mbx *m;
  1013.  
  1014.     m = (struct mbx *)p;
  1015.     m->stype = 'L';
  1016.     return (dombusers (argc, argv, p));
  1017. }
  1018.  
  1019.  
  1020. #ifdef TIPMAIL
  1021. int
  1022. dombslip(argc,argv,p)
  1023. int argc;
  1024. char *argv[];
  1025. void *p;
  1026. {
  1027. register struct mbx *m;
  1028.  
  1029.     m = (struct mbx *)p;
  1030.     if (m->type != TIP)    {
  1031.         tputs ("This command not configured for this interface\n");
  1032.         return (0);
  1033.     }
  1034.     if (m->privs & NO_SLIP)    {
  1035.         tputs (Noperm);
  1036.         return 0;
  1037.     }
  1038.     suspendTipMail ();
  1039.     return -2;
  1040. }
  1041. #endif
  1042.  
  1043.  
  1044. int
  1045. dombexpert(argc,argv,p)
  1046. int argc;
  1047. char *argv[];
  1048. void *p;
  1049. {
  1050. struct mbx *m;
  1051. struct usock *up;
  1052.  
  1053.     m = (struct mbx *)p;
  1054.  
  1055.     switch(m->stype) {
  1056.     case 'M':
  1057.         if(argc == 1)    {
  1058.             tprintf("-more- after %d lines\n",m->morerows);
  1059.             return 0;
  1060.         } else {
  1061.             m->morerows = atoi(argv[1]);
  1062.         }
  1063.         break;
  1064.     case 'A':
  1065.         m->sid ^= MBX_AREA;
  1066.         break;
  1067.     case 'G':
  1068.         m->sid ^= MBX_GFX;
  1069.     m->usecolor ^= 1;
  1070.         break;
  1071.     case 'N':
  1072.         m->sid ^= MBX_NRID;
  1073.         break;
  1074.     case 'S':
  1075.         m->sid ^= MBX_STATS;
  1076.         break;
  1077. #ifdef LZW
  1078.     case 'C':
  1079.         m->sid ^= MBX_TNOS;
  1080.     up = itop(m->user);
  1081.         if ((m->sid & MBX_TNOS) || (up->zout != NULLLZW))
  1082.             togglelzw (m->user, m->sid & MBX_TNOS);
  1083.         break;
  1084. #endif
  1085.     case ' ':
  1086.     case 'X':
  1087.         m->sid ^= MBX_EXPERT;
  1088.         break;
  1089.     default:
  1090.         return 0;
  1091.     }
  1092.     m->update = 1;
  1093.     return (expertstat (m));
  1094. }
  1095.  
  1096. int
  1097. dombexpand(argc,argv,p)
  1098. int argc;
  1099. char *argv[];
  1100. void *p;
  1101. {
  1102. struct mbx *m;
  1103. struct list *ap,*list;
  1104. char *arg, *orig, *newaddr, buf[LINELEN];
  1105. int loopindex;
  1106.  
  1107.     m = (struct mbx *)p;
  1108.     tprintf ("Address '%s' expands to: ", argv[1]);
  1109.     arg = argv[1];
  1110.     list = NULLLIST;
  1111.     orig = strdup (arg);
  1112.         /* rewrite address if possible */
  1113.     if((newaddr = rewrite_address(arg)) != NULLCHAR)
  1114.         if(strcmp(newaddr,arg) == 0){
  1115.             free(newaddr);
  1116.             newaddr = NULLCHAR;
  1117.         } else {
  1118.             strcpy(buf,newaddr);
  1119.             arg = buf;
  1120.         }
  1121.         list = NULLLIST;
  1122.     expandalias(&list,arg, orig);
  1123.     free (orig);
  1124.     if (strcmp(list->val,arg) == 0 && list->next == NULLLIST)
  1125.         if(newaddr == NULLCHAR){
  1126.             (void) tprintf("'%s'\n",arg);
  1127.             del_list(list);
  1128.             return 0;
  1129.         }
  1130.     ap = list;
  1131.     loopindex = 0;
  1132.     while (ap->next != NULLLIST){
  1133.         if (!(loopindex++ % 2))
  1134.             tputc ('\n');
  1135.         tputs ("     ");
  1136.         (void) tprintf("%-32.32s",ap->val);
  1137.         ap = ap->next;
  1138.     }
  1139.     tprintf ("%s     %s\n", (loopindex % 2) ? "" : "\n", ap->val);
  1140.     del_list(list);
  1141.     free(newaddr);
  1142.     return 0;
  1143. }
  1144.  
  1145.  
  1146. int
  1147. dombroute(argc,argv,p)
  1148. int argc;
  1149. char *argv[];
  1150. void *p;
  1151. {
  1152. struct mbx *m;
  1153. char *arg, *newaddr, buf[LINELEN];
  1154. int k, loopindex;
  1155.  
  1156.     arg = argv[1];
  1157.     tprintf ("Address '%s' routes to:", argv[1]);
  1158.         /* rewrite address if possible */
  1159.     if((newaddr = rewrite_address(arg)) != NULLCHAR)
  1160.         if(strcmp(newaddr,arg) == 0){
  1161.             free(newaddr);
  1162.             newaddr = NULLCHAR;
  1163.         } else {
  1164.             strcpy(buf,newaddr);
  1165.             arg = buf;
  1166.         }
  1167.     else
  1168.         newaddr = strdup (argv[1]);
  1169.     for (loopindex = 0,k = 0; k < Numfwds; k++)
  1170.         if (AREAlookup (newaddr, k))    {
  1171.             if (!(loopindex++ % 3))
  1172.                 tputs ("\n   ");
  1173.             (void) tprintf("%-25.25s",MyFwds[k]);
  1174.         }
  1175.     tputc ('\n');
  1176.     free (newaddr);
  1177.     return 0;        
  1178. }
  1179.  
  1180.  
  1181. #ifdef RMAIL
  1182. int
  1183. dombrmail(argc,argv,p)
  1184. int argc;
  1185. char *argv[];
  1186. void *p;
  1187. {
  1188. int orgchange;
  1189. struct mbx *m;
  1190. char *cp;
  1191.  
  1192.     m = (struct mbx *)p;
  1193.     if (!(m->sid & MBX_SID))    {    /* not available to BBSs */
  1194.         orgchange = m->change;
  1195.         m->change = -1;
  1196.         m->stype = 'C';
  1197.         cp = malloc (strlen (argv[1]) + 8);
  1198.         sprintf (cp, "rmail@%s", argv[1]);
  1199.         argv[1] = cp;
  1200.         dosend (argc, argv, p);
  1201.         m->change = orgchange;
  1202.         free (cp);
  1203.     }
  1204.     return 0;
  1205. }
  1206. #endif
  1207.  
  1208.  
  1209. #ifdef LZW
  1210. void
  1211. togglelzw(soc, mode)
  1212. int soc, mode;
  1213. {
  1214. struct usock *up;
  1215.  
  1216.     if((up = itop(soc)) == NULLUSOCK)
  1217.         return;
  1218.         tprintf ("%c%c%c%c", IAC, COMPRESSED, (Lzwmode) ? 'f' : 'c', Lzwbits);
  1219.     usflush(soc);
  1220. /*    if(socklen(soc,0)) */    /* discard any remaining input */
  1221. /*        recv_mbuf(soc,NULL,0,NULLCHAR,0);    */
  1222.     if(mode)    {
  1223.             lzwinit (soc, Lzwbits, Lzwmode);
  1224.             up->zin->maxbits = -1;
  1225.     } else
  1226.         lzwfree (up);
  1227.     usflush(soc);
  1228.     if(socklen(soc,0)) /* discard any remaining input */
  1229.         recv_mbuf(soc,NULL,0,NULLCHAR,0);
  1230. }
  1231. #endif
  1232.  
  1233.  
  1234. int
  1235. dombset(argc,argv,p)
  1236. int argc;
  1237. char *argv[];
  1238. void *p;
  1239. {
  1240. struct mbx *m;
  1241.  
  1242.     m = (struct mbx *)p;
  1243.     m->stype = toupper (*argv[1]);
  1244.     if (!strnicmp(argv[1], "Si", 2))
  1245.         m->stype = '$';
  1246.     if (m->stype == 'F' || m->stype == '$')
  1247.         return (dombupload(argc, argv, p));
  1248.     else
  1249.         return (dombexpert(argc - 1, &argv[1], p));
  1250. }
  1251.  
  1252.  
  1253. /* Routine for quickly checking an area for messages that are new to this user.
  1254.    This routine reads the area.ctl files, which contains a bid for each message.  */
  1255.  
  1256. static int
  1257. quickstat(m, area)
  1258. register struct mbx *m;
  1259. char *area;
  1260. {
  1261. long last, newlast, lastone;
  1262. char oldarea[20], buf[256];
  1263. FILE *fp;
  1264. register int retval = 0;
  1265.  
  1266. #ifdef USERLOG
  1267.     last = m->lastread;
  1268.     newlast = m->newlastread;
  1269.     m->lastread = 0;
  1270.     strcpy (oldarea, m->area);
  1271.     strcpy (m->area, area);
  1272.     /* only read last read message-id if current area is a public area
  1273.      * and not 'help' or area starts with 'sys'
  1274.      * read in all cases if a SYSOP
  1275.      */
  1276.  
  1277.     if( (stricmp(area,"help") && isarea(area)) || !strnicmp(m->area,"sys",3) || (m->privs & SYSOP_CMD))
  1278.         getlastread(m);
  1279.     pwait (NULL);
  1280.     lastone = m->lastread;
  1281.     m->lastread = last;
  1282.     m->newlastread = newlast;
  1283.     strcpy (m->area, oldarea);
  1284.     sprintf (buf, "%s/CONTROL/%s.ctl", Mailspool, area);
  1285.     if ((fp = fopen (buf, READ_BINARY)) != NULLFILE)    {
  1286.         struct let lt;
  1287.         long size;
  1288.         size = (filelength (fileno(fp)) - sizeof(struct let));
  1289.         fseek (fp, size, SEEK_SET);
  1290.         fread (<, sizeof(struct let), 1, fp);
  1291.         fclose(fp);
  1292.         if (lt.bid > lastone)
  1293.             retval = 1;
  1294.     }
  1295.     pwait (NULL);
  1296. #endif
  1297.     return retval;
  1298. }
  1299.  
  1300.  
  1301.  
  1302. #ifdef USERLOG
  1303. void
  1304. quickscan (m, olduser)
  1305. struct mbx *m;
  1306. int olduser;
  1307. {
  1308. char *cp;
  1309. FILE *fp;
  1310. char buf[MBXLINE];
  1311. char out[80], *initmsg;
  1312. int found = 0, length = 3;
  1313. /* int total, new, hold;    */
  1314.  
  1315.     cp = Arealist;
  1316.     if((m->privs & SYSOP_CMD) && (!access(AreaSlist, 0)))
  1317.         cp = AreaSlist;
  1318.     if((fp = fopen(cp,READ_TEXT)) == NULLFILE)
  1319.         return;
  1320.     if (olduser)
  1321.         initmsg = "You have unread messages, in the following message areas:\n";
  1322.     else
  1323.         initmsg = "As a new user, you will find messages in the following message areas:\n";
  1324.     strcpy (out, "   ");
  1325.     while(fgets(buf,MBXLINE,fp) != NULLCHAR)     {
  1326.         pwait (NULL);
  1327.         if(isalnum(buf[0]))     { /* skip comments */
  1328.             if((cp=strpbrk(buf," \t")) != NULLCHAR)
  1329.                 *cp = '\0';
  1330. /*            statarea (m, buf, &total, &new, &hold, 0);
  1331.             if (new)    {        */
  1332.             if (quickstat (m, buf))        {
  1333.                 if (!found)    {
  1334.                     tputs (initmsg);
  1335.                     found++;
  1336.                     }
  1337.                 length += (strlen(buf) + 2);
  1338.                 strcat (out, buf);
  1339.                 strcat (out, "  ");
  1340.                 }
  1341.             if (length > 70)    {
  1342.                 tputs (out);
  1343.                 tputc('\n');
  1344.                 out[3] = 0;
  1345.                 length = 3;
  1346.                 }
  1347.             }
  1348.         }
  1349.     if (length != 3)    {
  1350.         tputs (out);
  1351.         tputc('\n');
  1352.     }
  1353.     fclose (fp);
  1354.     if (!found)
  1355.         tputs ("No unread messages in the public areas! You are up-to-date!\n");
  1356. }
  1357. #endif
  1358.  
  1359.  
  1360. int
  1361. dombtime(argc,argv,p)
  1362. int argc;
  1363. char *argv[];
  1364. void *p;
  1365. {
  1366. struct mbx *m;
  1367. time_t isnow;
  1368.  
  1369.     m = (struct mbx *) p;
  1370.     time (&isnow);
  1371.     tprintf ("The system time at '%s' is now: %s\n", Hostname, ptime(&isnow));
  1372.     return 0;
  1373. }
  1374.  
  1375.  
  1376. int
  1377. dombquote(argc,argv,p)
  1378. int argc;
  1379. char *argv[];
  1380. void *p;
  1381. {
  1382. struct mbx *m;
  1383. char *host, *user = NULLCHAR, buf[8], *newargv[3];
  1384.  
  1385.     host = Hostname;
  1386.     if(argc == 2)
  1387.         host = argv[1];
  1388.     m = (struct mbx *) p;
  1389.     newargv[0] = "t";
  1390.     newargv[1] = host;
  1391.     sprintf(buf,"%d",IPPORT_QUOTE);
  1392.     newargv[2] = buf;
  1393.     SecureTelnet = 0;
  1394.     return dombtelnet(3,newargv,p);
  1395. }
  1396.  
  1397. void
  1398. informGroup (action, group, user, buf, old, new, in)
  1399. char *action, *group, *user, *buf;
  1400. FILE *old, *new, *in;
  1401. {
  1402. char subj[68], *cp;
  1403.  
  1404.     sprintf (subj, "%s: SUBSCRIBED %s", user, group);
  1405.     while (fgets(buf,50,old) != NULLCHAR)    {
  1406.         fputs (buf, new);
  1407.         if (*buf != ' ')
  1408.             break;
  1409.         if (buf[strlen (buf) - 2] == 'I')    {
  1410.             if ((cp = strchr (&buf[1], ' ')) != NULLCHAR)
  1411.                 *cp = 0;
  1412.             if (in)
  1413.                 rewind (in);
  1414.             rdaemon (in, NULLCHAR, &buf[1], subj, 'P', 0);
  1415.         }
  1416.     }
  1417. }
  1418.  
  1419.  
  1420. int
  1421. isgroup (group)
  1422. char *group;
  1423. {
  1424. FILE *old;
  1425. register len, retval = 0;
  1426. char buf[80];
  1427.  
  1428. #if 0
  1429.     if (group && (len = strlen (group)) > 6)
  1430.         return 0;
  1431. #else
  1432.     len = strlen (group);
  1433. #endif
  1434.     if ((old = fopen(Group, UPDATE_TEXT)) == NULLFILE)
  1435.         return 0;
  1436.     while (fgets(buf,80,old) != NULLCHAR)    {
  1437.         if (!strnicmp (buf, group, len) && buf[len] == ':')    {
  1438.             retval = 1;
  1439.             break;
  1440.         }
  1441.     }
  1442.     fclose (old);
  1443.     return retval;
  1444. }
  1445.  
  1446. int
  1447. groupcommand (action, group, user, local, out, in)
  1448. char *action, *group, *user;
  1449. int local;
  1450. FILE **out, *in;
  1451. {
  1452. FILE *new, *old;
  1453. char *newname, *cp;
  1454. register int len, found = 0, retval = 0;
  1455. char which, buf[80], subj[68];
  1456.  
  1457. #if 0
  1458.     if (group && (len = strlen (group)) > 6)
  1459.         return 0;
  1460. #else
  1461.     len = strlen (group);
  1462. #endif
  1463.     if ((old = fopen(Group, UPDATE_TEXT)) == NULLFILE)
  1464.         return 0;
  1465.     newname = (char *) malloc (strlen (Group) + 5);
  1466.     sprintf (newname, "%s.new", Group);
  1467.     if ((new = fopen(newname, CREATE_TEXT)) == NULLFILE)    {
  1468.         fclose (old);
  1469.         free (newname);
  1470.         return 0;
  1471.     }
  1472.     *action = tolower (*action);
  1473.     if (*action == 'l')    {    /* list groups */
  1474.         if (!local)
  1475.             fprintf (new, "Index of mailing lists/groups\n\n");
  1476.         while (fgets(buf,50,old) != NULLCHAR)    {
  1477.             if (*buf != ' ' && (cp = strchr (buf, ':')) != 0)    {
  1478.                 *cp++ = '\n';
  1479.                 *cp = 0;
  1480.                 if (!local)
  1481.                     fputs (buf, new);
  1482.                 else
  1483.                     tputs (buf);
  1484.             }
  1485.         }
  1486.         if (!local)    {
  1487.             rewind (new);
  1488.             strcpy (subj, "GROUP LISTING");
  1489.             rdaemon (new, NULLCHAR, user, subj, 'P', 0);
  1490.         }
  1491.         retval = 1;
  1492.         goto confuzed;
  1493.     }
  1494.     if (*action != 'a')    {
  1495.         while (fgets(buf,50,old) != NULLCHAR)    {
  1496.             if (!strnicmp (buf, group, len) && buf[len] == ':')    {
  1497.                 found = 1;
  1498.                 break;
  1499.             }
  1500.             fputs (buf, new);
  1501.         }
  1502.         if (!found)
  1503.             goto confuzed;
  1504.         if (*action != 'd')
  1505.             fputs (buf, new);
  1506.     }
  1507.     switch (tolower (*action))    {
  1508.         case 'a':    fprintf (new, "%s:\n\n", group);
  1509.                 break;
  1510.         case 'i':    fprintf (new, " %s I\n", user);
  1511.                 break;
  1512.         case 's':    fprintf (new, " %s S\n", user);
  1513.                 rip (buf);
  1514.                 if (local)
  1515.                     DisplayFile (&buf[len+2], Curproc->output);
  1516.                 else
  1517.                     *out = fopen (&buf[len+2], READ_TEXT);
  1518.                 informGroup (action, group, user, buf, old, new, in);
  1519.                 break;
  1520.         case 'u':    len = strlen (user);
  1521.                 which = (strlen (action) < 3) ? 's' : tolower (action[2]);
  1522.                 while (fgets(buf,50,old) != NULLCHAR)    {
  1523.                     if (*buf != ' ')    {
  1524.                         fputs (buf, new);
  1525.                         break;
  1526.                     }
  1527.                     if (strnicmp (&buf[1], user, len) ||
  1528.                         tolower (buf[strlen (buf) - 2]) != which)
  1529.                             fputs (buf, new);
  1530.                     else
  1531.                         break;
  1532.                 }
  1533.                 break;
  1534.         case 'd':    while (fgets(buf,50,old) != NULLCHAR)
  1535.                     if (*buf != ' ')    {
  1536.                         if (*buf != '\n')
  1537.                             fputs (buf, new);
  1538.                         break;
  1539.                     }
  1540.                 break;
  1541.         default:    goto confuzed;
  1542.     }
  1543.     while (fgets(buf,50,old) != NULLCHAR)
  1544.         fputs (buf, new);
  1545.     fclose (new);
  1546.     fclose (old);
  1547.     unlink (Group);
  1548.     rename (newname, Group);
  1549.     free (newname);
  1550.     return 1;
  1551.  
  1552. confuzed:
  1553.     fclose (new);
  1554.     fclose (old);
  1555.     unlink (newname);
  1556.     free (newname);
  1557.     return retval;
  1558. }
  1559.  
  1560.  
  1561. int
  1562. dombgroup(argc,argv,p)
  1563. int argc;
  1564. char *argv[];
  1565. void *p;
  1566. {
  1567. struct mbx *m;
  1568. char cmd;
  1569.  
  1570.     m = (struct mbx *) p;
  1571.  
  1572.     cmd = tolower (*argv[1]);
  1573.     if (cmd != 's' && cmd != 'u' && cmd != 'l')
  1574.         if (m->privs == -1 || !(m->privs & SYSOP_CMD))
  1575.             goto denied;
  1576.     if (cmd != 'l' && argc < 3)
  1577.         goto denied;
  1578.     if (!groupcommand (argv[1], (argc > 2) ? argv[2] : NULLCHAR, (argc > 3 && m->privs & SYSOP_CMD) ? argv[3] : m->name, 1, (FILE **)0, (FILE *)0))
  1579. denied:        tputs ("Denied!\n");
  1580.     return 0;
  1581. }
  1582.  
  1583.  
  1584. #ifdef TUTOR
  1585. extern int Stutor, Snews;
  1586.  
  1587. int
  1588. dombtutor(argc,argv,p)
  1589. int argc;
  1590. char *argv[];
  1591. void *p;
  1592. {
  1593. struct mbx *m;
  1594.  
  1595.     m = (struct mbx *) p;
  1596.  
  1597.         if(Stutor == -1) {
  1598.             tputs("Tutorial server not enabled\n");
  1599.             return 0;
  1600.         }
  1601.         log(m->user,"MBOX TUTORIAL: %s",m->name);
  1602.         m->state = MBX_TUTOR;
  1603.         tutorserv(m->name, m, 0, m->usecolor, 0);
  1604.     return 0;
  1605. }
  1606.  
  1607.  
  1608. int
  1609. dombnews(argc,argv,p)
  1610. int argc;
  1611. char *argv[];
  1612. void *p;
  1613. {
  1614. struct mbx *m;
  1615.  
  1616.     m = (struct mbx *) p;
  1617.  
  1618.         if(Snews == -1) {
  1619.             tputs("News Center not enabled\n");
  1620.             return 0;
  1621.         }
  1622.         log(m->user,"MBOX NEWS: %s",m->name);
  1623.         m->state = MBX_TUTOR;
  1624.         tutorserv(m->name, m, 2, m->usecolor, 0);
  1625.     return 0;
  1626. }
  1627. #endif
  1628.  
  1629.  
  1630. char *
  1631. wpage_exp (to, hier, exphome)
  1632. char *to;
  1633. int hier;
  1634. int exphome;    /* append and expand home bbs name ? */
  1635. {
  1636. char DFAR *cp;
  1637. char DFAR *cp2;
  1638. char origbbs[40], buf[12];
  1639.  
  1640. /* This section adds the HOME BBS to any messages to known users that do
  1641.    not have "@bbs" portions of the TO address, except when user is a BBS    */
  1642.  
  1643.     cp2=strchr(to,'@');
  1644.     cp = NULLCHAR;
  1645.     if ((cp2 == NULLCHAR) && (cp = findhome (to)) != (char DFAR *) NULL)    {
  1646.     if (cp != (char DFAR *) -1)    {    /* home no here */
  1647.             sprintf (origbbs, "%s@%s", to, cp);
  1648.             free (to);
  1649.             free (cp);
  1650.             to = strdup (origbbs);
  1651.     }
  1652.     }
  1653. #ifdef WPAGES
  1654. /* This section looks up the destination bbs in the White Pages file, if user not a BBS
  1655.    If found, the complete address is substituted    */
  1656.  
  1657.     if (cp != (char DFAR *) -1)    {    /* if home not here */
  1658.         cp2=strchr(to,'@');
  1659.         if (cp2 == NULLCHAR)    {    /* no dest BBS given */
  1660.             if ((cp2 = wpageCheck (to, 0, 0)) != NULLCHAR)    { /* found the bbs */
  1661.                 free (to);
  1662.                 strlwr (cp2);
  1663.                 to = cp2;
  1664.             }
  1665.             cp2 = strchr(to, '@');
  1666.         }
  1667.         if (hier && cp2 != NULLCHAR)    {    /* we have a dest bbs, get correct, full haddress */
  1668.                    cp = cp2++;
  1669.             if ((cp2 = wpageCheck (cp2, 1, 0)) != NULLCHAR)    {
  1670.                     *cp = '\0';
  1671.                     sprintf (origbbs, "%s@%s", to, cp2);
  1672.                         free (to);
  1673.                         free (cp2);
  1674.                            strlwr (origbbs);
  1675.                         to = strdup (origbbs);            
  1676.             }
  1677.         }
  1678.     } else if (exphome)    {
  1679.     pax25(buf,Mycall);
  1680.     if((cp = strchr(buf,'-')) != NULLCHAR)
  1681.         *cp = '\0'; /* remove SSID */
  1682.         sprintf (origbbs, "%s@%s%s%s", to, buf,
  1683.         (Mbhaddress != NULLCHAR) ? "." : "",
  1684.         (Mbhaddress != NULLCHAR) ? Mbhaddress : "");
  1685.     free (to);
  1686.         to = strdup (origbbs);
  1687.     }
  1688. #endif
  1689.     pwait (NULL);
  1690.     return (to); 
  1691. }
  1692.  
  1693. #ifdef WPAGES
  1694. extern int MbWpages;
  1695.  
  1696. int
  1697. dombwpages(argc,argv,p)
  1698. int argc;
  1699. char *argv[];
  1700. void *p;
  1701. {
  1702. struct mbx *m;
  1703. char buf[14], *cp, *cp2, *cp3;
  1704.  
  1705.     m = (struct mbx *)p;
  1706.     if(!(m->privs & SYSOP_CMD) && argc > 2)    {
  1707.         tputs ("Sorry, command is only available to the SYSOP!\n");
  1708.         return 0;
  1709.     }
  1710.     if (argc == 2)    {    /* lookup */
  1711.         cp = wpageCheck (argv[1], 0, 0);
  1712.         if (!cp)
  1713.             tputs ("Sorry, user not in whitepages! If local user, try \"ML user\"...\n");
  1714.         else    {
  1715. #if 0
  1716.             cp2 = strchr (cp, '@');
  1717.             *cp2++ = 0;
  1718.             cp3 = wpageCheck (cp2, 1, 0);
  1719.             if (!cp3)
  1720.                 cp3 = cp2;
  1721.             strupr (argv[1]);
  1722.             strupr (cp3);
  1723.             tprintf ("White Pages lists this person as '%s@%s'\n", argv[1], cp3);
  1724.             if (cp3 != cp2)
  1725.                 free (cp3);
  1726. #else
  1727.             cp2 = wpage_exp (strdup(argv[1]), 1, 1);
  1728.             strupr (cp2);
  1729.             tprintf ("White Pages lists this person as '%s'\n", cp2);
  1730.             free (cp2);
  1731. #endif
  1732.             free (cp);
  1733.         }
  1734.     } else    {    /* else, setting it */
  1735.         if (argv[2][0] != '@')
  1736.             tputs ("Syntax: WP user @bbsname\n");
  1737.         else    {
  1738.             sprintf (buf, "%s%s", argv[1], argv[2]);
  1739.             wpageAdd (buf, 0, 1);
  1740.         }
  1741.     }
  1742.     return 0;
  1743. }
  1744.  
  1745.  
  1746. void
  1747. wpageUpdate(fp, string, entry, oldtime, bbs, updateit)
  1748. FILE *fp;
  1749. char *string, *entry, *oldtime;
  1750. int bbs, updateit;
  1751. {
  1752. time_t now;
  1753. char buf[14], *cp;
  1754.  
  1755. /* parameters string and oldtime are not being used, yet */
  1756.  
  1757.     if (updateit && !bbs)    {    /* not updating bbs's, yet */
  1758.         strncpy (buf, string, 13);
  1759.         buf[13] = 0;
  1760.         if ((cp = strchr(buf, '.')) != NULLCHAR)
  1761.             *cp = 0;
  1762.         entry = buf;
  1763.     }
  1764.     time(&now);
  1765.     fprintf(fp,"%-*s %-14ld\n",(bbs) ? 32 : 13, entry,now); /* update time stamp */
  1766.     pwait (NULL);
  1767. }
  1768.  
  1769.  
  1770. /* Returns a copy (strdup'ed) of existing entry if string is in whitepages file */
  1771. char *
  1772. wpageCheck(string, bbs, updateit)
  1773. char *string;
  1774. int bbs, updateit;
  1775. {
  1776. register FILE *fp;
  1777. char buf[LINELEN], *retval = NULLCHAR;
  1778. register char *cp;
  1779. int result, thelen;
  1780. int entrysize;
  1781. char *fname;
  1782.  
  1783.     if (!MbWpages || string == NULLCHAR || !*string)
  1784.         return (retval);
  1785.     if (!strnicmp (string, "sysop", 5))
  1786.         return (retval);
  1787.     entrysize = (bbs) ? 49 : 30;
  1788.     fname = (bbs) ? WhitePagesBBS : WhitePages;
  1789.     if ((cp = strchr(string, (bbs) ? '.' : '@')) != NULLCHAR)
  1790.         thelen = (int) (cp - string);
  1791.     else
  1792.         thelen = strlen (string);
  1793.     result = searchfile (string, fname, buf, entrysize, 0, thelen);
  1794.     if (result != -1)    {    /* found it */
  1795.         if( ((cp=strpbrk(buf," \t")) != NULLCHAR))
  1796.             *cp = '\0';
  1797.         rip(buf);
  1798.         retval = strdup (buf);
  1799.         fp = fopen (fname, UPDATE_TEXT);
  1800.         fseek (fp, (long) (long)result * (long) entrysize, 0);
  1801.         wpageUpdate (fp, string, buf, &buf[(bbs) ? 33 : 14], bbs, updateit);
  1802.         fclose(fp);
  1803.     }
  1804.     return retval;
  1805. }
  1806.      
  1807.  
  1808. void
  1809. wpageAdd (entry, bbs, updateit)
  1810. char *entry;
  1811. int bbs, updateit;
  1812. {
  1813. time_t now;
  1814. FILE *fp;
  1815. char *last, buf[14];
  1816.  
  1817.     if (!MbWpages || entry == NULLCHAR)
  1818.         return;
  1819.     if (!strnicmp (entry, "sysop", 5))
  1820.         return;
  1821.     last = wpageCheck (entry, bbs, updateit);
  1822.     free (last);
  1823.     if (!last)    {
  1824.         time(&now);
  1825.         if (!bbs)    {
  1826.             strncpy (buf, entry, 13);
  1827.             buf[13] = 0;
  1828.             if ((last = strchr(buf, '.')) != NULLCHAR)
  1829.                 *last = 0;
  1830.             entry = buf;
  1831.         }
  1832.         if((fp = fopennew((bbs) ? WhitePagesBBS : WhitePages,APPEND_TEXT)) != NULLFILE) {
  1833.             fprintf(fp,"%-*s %-14ld\n",(bbs) ? 32 : 13, entry,now); /* Save h_addr in whitepages file */
  1834.             pwait (NULL);
  1835.             fclose(fp);
  1836.         }
  1837.     }
  1838.  
  1839. }
  1840. #endif
  1841.  
  1842.  
  1843. /* Returns true if string is in history file or if string appears to be a
  1844.  * message id generated by our system.
  1845.  */
  1846. int
  1847. msgidcheck(string)
  1848. register char *string;
  1849. {
  1850. char buf[LINELEN];
  1851. register char *cp;
  1852.  
  1853.      if(string == NULLCHAR)
  1854.       return 0;
  1855.      /* BID's that we have generated ourselves are not kept in the history
  1856.       * file. Such BID's are in the nnnn_hhhh form, where hhhh is a part of
  1857.       * our hostname, truncated so that the BID is no longer than 11
  1858.       * characters.
  1859.       */
  1860.      if((cp = strchr(string,'_')) != NULLCHAR && *(cp+1) != '\0' && 
  1861.     strnicmp(cp+1,Hostname,strlen(cp+1)) == 0)
  1862.       return 1;
  1863.  
  1864.      if (searchfile (string, Historyfile, buf, 30, 0, 0) != -1)
  1865.          return 1;
  1866.      return 0;
  1867. }
  1868.      
  1869.  
  1870. /* Releases a bid from the history file. Used when a personal message
  1871.  * is forwarded off the system. Lets it be able to come back here,
  1872.  * if needed.
  1873.  */
  1874. void
  1875. msgiddelete(string)
  1876. register char *string;
  1877. {
  1878. register FILE *fp;
  1879. char buf[LINELEN];
  1880. int index;
  1881.  
  1882.     if(string == NULLCHAR)
  1883.         return;
  1884.  
  1885.     index = searchfile (string, Historyfile, buf, 30, 0, 0);
  1886.     if (index == -1)
  1887.         return;
  1888.  
  1889.     if((fp = fopen(Historyfile,UPDATE_TEXT)) == NULLFILE)
  1890.         return;
  1891.     fseek (fp, (long) ((long) index * (long) 30), 0);
  1892.     fputc ('$', fp);
  1893.     fclose(fp);
  1894.     pwait (NULL);
  1895. }
  1896.      
  1897.  
  1898. int
  1899. dombfdesc(argc,argv,p)
  1900. int argc;
  1901. char *argv[];
  1902. void *p;
  1903. {
  1904. struct mbx *m;
  1905. char *file, *cp, *nm;
  1906. FILE *fp;
  1907. int k;
  1908. unsigned attr;
  1909. char name[14];
  1910.     
  1911.     m = (struct mbx *) p;
  1912.     if (!(file = permtest (m->path, m->privs, argv[1], RETR_CMD, NULLCHAR, 0)))    {
  1913.         tputs (Noperm);
  1914.         return 0;
  1915.     }
  1916.  
  1917.     _dos_getfileattr (file, &attr);
  1918.     nm = strrchr (file, '/');
  1919.     *nm++ = 0;
  1920.     if(attr & FA_DIREC)    {
  1921.         sprintf (name, "%s/", nm);
  1922.         nm = name;
  1923.         }
  1924.     cp = pathname (file,index_dat);
  1925.     if ((fp = fopen (cp, APPEND_TEXT)) == NULLFILE)    {
  1926.         tputs ("Can't open description file!\n");
  1927.         return 0;
  1928.     }
  1929.     fprintf (fp, "%-12s", nm);
  1930.     free (file);
  1931.     free (cp);
  1932.     tputs ("Enter description lines, each line 37 characters maximum.\n'/EX' when complete:\n");
  1933.     for (k = 1; k < 38; k++)
  1934.         tputc ('0' + (k % 10));
  1935.     tputc ('\n');
  1936.     while(mbxrecvline(m) != -1)    {
  1937.         if (!strnicmp (m->line, "/ex", 3))    {
  1938.             fclose (fp);
  1939.             return (0);
  1940.         }
  1941.         fprintf (fp, " %-37.37s\n", skipwhite (m->line));
  1942.     }
  1943.     fclose (fp);
  1944.     return (-2);    /* socket closed here! */
  1945. }
  1946.  
  1947.  
  1948.  
  1949. int
  1950. dodownload(argc,argv,p)
  1951. int argc;
  1952. char *argv[];
  1953. void *p;
  1954. {
  1955. struct mbx *m;
  1956. FILE *fp;
  1957. char *file;
  1958.  
  1959.     m = (struct mbx *)p;
  1960.     if (m->stype == 'I')
  1961.         return (dowhat (argc, argv, p));
  1962.     if (m->stype == 'E')
  1963.         return (dozap (argc, argv, p));
  1964.  
  1965.     if (!(file = permtest(m->path, m->privs,argv[1],RETR_CMD, NULLCHAR, 0)))    {
  1966.             tputs(Noperm);
  1967.             mail_error("%s: download denied: %s\n",m->name,cmd_line(argc,argv,m->stype));
  1968.         return 0;
  1969.     }
  1970.     m->state = MBX_DOWNLOAD;
  1971. #ifdef TIPMAIL
  1972. #ifdef XMODEM
  1973.     if (m->stype=='X') { 
  1974.           if (m->type==TIP){   /* xmodem send tip only */
  1975.         m->state = MBX_XMODEM_TX;
  1976. #ifdef MBXTDISC
  1977.     /* disable the mbox inactivity timeout timer - WG7J */
  1978.         stop_timer(&m->tdisc);   
  1979. #endif
  1980.         doxmodem('S',file,m);
  1981.         return 0;
  1982.           } else {
  1983.         tprintf("Xmodem on TIP connects only\n");
  1984.         return 0;
  1985.           }
  1986.     }
  1987. #endif
  1988. #endif
  1989.     if((fp = fopen(file,READ_TEXT)) == NULLFILE)
  1990.         tprintf("Can't open \"%s\": %s\n",file,sys_errlist[errno]);
  1991.     else        {
  1992. #ifdef MBXTDISC
  1993.             /* disable the mbox inactivity timeout timer - WG7J */
  1994.             stop_timer(&m->tdisc);
  1995. #endif
  1996.         if(m->stype == 'U')    {            /* uuencode ? */
  1997.             fclose(fp);
  1998.             fp = fopen(file,READ_BINARY);    /* assume non-ascii */
  1999.             uuencode(fp,m->user,file);
  2000.         } else
  2001.             sendfile(fp,m->user,ASCII_TYPE,0);
  2002.         fclose(fp);
  2003.     }
  2004.     free(file);
  2005.     return 0;
  2006. }
  2007.  
  2008.  
  2009. int
  2010. dombupload(argc,argv,p)
  2011. int argc;
  2012. char *argv[];
  2013. void *p;
  2014. {
  2015. struct mbx *m;
  2016. FILE *fp;
  2017. char *file;
  2018.  
  2019.     m = (struct mbx *)p;
  2020.     if (m->stype == 'S')    {
  2021.         m->stype = 'L';
  2022.         return (dombusers (argc, argv, p));
  2023.     }
  2024.     if (m->stype == 'F')    {
  2025.         sprintf (m->line, "%s/%s", Fdir, m->name);
  2026.         file = strdup(m->line);
  2027.     } else if (m->stype == '$')    {
  2028.         sprintf (m->line, "%s/%s.sig", Signature, m->name);
  2029.         file = strdup(m->line);
  2030.     } else if(!(file = permtest(m->path, m->privs,argv[1],STOR_CMD, NULLCHAR, 0)))    {
  2031.         tputs(Noperm);
  2032.             mail_error("%s: upload denied: %s\n",m->name,cmd_line(argc,argv,m->stype));
  2033.         return 0;
  2034.     }
  2035. #ifdef TIPMAIL
  2036. #ifdef XMODEM
  2037.     if (m->stype=='X'){ 
  2038.         if (m->type==TIP){   /* xmodem receive tip only */
  2039.             m->state = MBX_XMODEM_RX;
  2040. #ifdef MBXTDISC
  2041.     /* disable the mbox inactivity timeout timer - WG7J */
  2042.             stop_timer(&m->tdisc);   
  2043. #endif
  2044.             doxmodem('R',file,m);
  2045.             return 0;
  2046.         } else {
  2047.             tprintf("Xmodem on TIP connects only\n");
  2048.             return 0;
  2049.         }
  2050.     }
  2051. #endif
  2052. #endif
  2053.     
  2054.     if((fp = fopen(file,WRITE_TEXT)) == NULLFILE)    {
  2055.         tprintf("Can't create \"%s\": %s\n",file,sys_errlist[errno]);
  2056.         free(file);
  2057.         return 0;
  2058.     }
  2059.     log(m->user,"MBOX upload: %s",file);
  2060.     m->state = MBX_UPLOAD;
  2061.     tprintf("Send %s,  %s",(m->stype == 'F') ? "personal information" : (m->stype == 'S') ? "signature information" : "file", Howtoend);
  2062.     for(;;)        {
  2063.         if(mbxrecvline(m) == -1)    {
  2064.             unlink(file);
  2065.             break;
  2066.         }
  2067.         if(*m->line == 0x01 || !stricmp (m->line, "/abort"))    {  /* CTRL-A */
  2068.             unlink(file);
  2069.             tputs(MsgAborted);
  2070.             break;
  2071.         }
  2072.         if(*m->line == CTLZ || !strnicmp("/ex",m->line,3) || !stricmp(m->line, "."))
  2073.             break;
  2074.         fputs(m->line,fp);
  2075. #if !defined(UNIX) && !defined(__TURBOC__) && !defined(AMIGA) && !defined(TNOS_68K)
  2076.         /* Needed only if the OS uses a CR/LF
  2077.          * convention and putc doesn't do
  2078.          * an automatic translation
  2079.          */
  2080.         if(putc('\r',fp) == EOF)
  2081.             break;
  2082. #endif
  2083.         if(putc('\n',fp) == EOF)
  2084.             break;
  2085.     }
  2086.     free(file);
  2087.     fclose(fp);
  2088.     return 0;
  2089. }
  2090.  
  2091. void
  2092. bbsbump (user, zap)
  2093. char *user;
  2094. int zap;    /* if zap=1, remove entry, else just mark for bumping */
  2095. {
  2096. int i;
  2097. struct mbx *m;
  2098.  
  2099.     /* check the mailbox users */
  2100.     for(i = 0; i < NUMMBX; i++)    {
  2101.         if((m = Mbox[i]) != NULLMBX)    {
  2102.             if(!stricmp(m->name,user))
  2103.                 break;
  2104.         }
  2105.     }
  2106.     if(i != NUMMBX)    {
  2107.         if (zap)
  2108.             exitbbs(m);
  2109.         else
  2110.             m->privs |= EXCLUDED_CMD;
  2111.     }
  2112. }
  2113.  
  2114.  
  2115. int
  2116. dobump(argc,argv,p)
  2117. int argc;
  2118. char *argv[];
  2119. void *p;
  2120. {
  2121. int i,s;
  2122. struct mbx *m;
  2123.  
  2124.     m = (struct mbx *)p;
  2125.     if(!(m->privs & SYSOP_CMD))
  2126.         tputs ("Sorry, command is only available to the SYSOP!\n");
  2127.     else
  2128.         bbsbump (argv[1], ((argc > 2) && !strnicmp ("now", argv[2], 3)) ? 1 : 0);
  2129.     return 0;
  2130. }
  2131.  
  2132. /* uuencode a file -- translated from C++; both versions copyright 1990
  2133.    by David R. Evans, G4AMJ/NQ0I
  2134. */
  2135.  
  2136. static int
  2137. uuencode(infile,s,infilename)
  2138. FILE *infile;
  2139. int s;            /* output socket */
  2140. char *infilename;
  2141. {
  2142. int n_read_so_far = 0, n_written_so_far = 0, in_chars, n, mode = 0755;
  2143. unsigned long cnt = 0;
  2144. unsigned char in[3], out[4], line[100];
  2145. #ifdef UNIX
  2146. struct stat stb;
  2147.   
  2148.   if(stat(infilename,&stb) != -1)
  2149.        mode = stb.st_mode & 0777;    /* get real file protection mode */
  2150. #endif
  2151.   usprintf(s, "begin %03o %s\n", mode, infilename);
  2152.  
  2153.   /* do the encode */
  2154.  for(;;){    
  2155.     in_chars = fread(in, 1, 3, infile);
  2156.     out[0] = in[0] >> 2;
  2157.     out[1] = in[0] << 6;
  2158.     out[1] = out[1] >> 2;
  2159.     out[1] = out[1] | (in[1] >> 4);
  2160.     out[2] = in[1] << 4;
  2161.     out[2] = out[2] >> 2;
  2162.     out[2] = out[2] | (in[2] >> 6);
  2163.     out[3] = in[2] << 2;
  2164.     out[3] = out[3] >> 2;
  2165.     for (n = 0; n < 4; n++)
  2166.       out[n] += ' ';
  2167.     n_read_so_far += in_chars;
  2168.     for (n = 0; n < 4; n++)
  2169.       line[n_written_so_far++] = out[n];
  2170.     if (((in_chars != 3) || (n_written_so_far == 60)) && n_read_so_far > 0) {
  2171.       line[(n_read_so_far + 2) / 3 * 4] = '\0';
  2172.       
  2173.       usprintf(s,"%c%s\n",n_read_so_far + ' ', line);
  2174.       cnt += n_read_so_far;
  2175.       n_read_so_far = 0;
  2176.       n_written_so_far = 0;
  2177.     }
  2178.     if (in_chars == 0)
  2179.       break;
  2180.   }
  2181.   if (usprintf(s," \nend\nsize %lu\n", cnt) == EOF)
  2182.     return 1;
  2183.   return 0;
  2184. }
  2185.  
  2186. #endif /* MAILBOX */
  2187.  
  2188.  
  2189.